################################################################################
# 版权所有 (C) 2012-2013 Leap Motion, Inc. 保留所有权利。                        #
# Leap Motion 特有和保密的信息，禁止分发。                                    #
# 使用受 Leap Motion SDK 协议的条款约束，该协议可在                           #
# https://developer.leapmotion.com/sdk_agreement，或另一份协议中获得。           #
################################################################################

# 导入 Leap Motion 模块和系统模块
import Leap, sys, thread, time
# 从 Leap 模块中导入手势类型
from Leap import CircleGesture, KeyTapGesture, ScreenTapGesture, SwipeGesture

# 创建 SampleListener 类，继承自 Leap.Listener
class SampleListener(Leap.Listener):
    # 定义手指、骨骼和状态的名称列表
    finger_names = ['Thumb', 'Index', 'Middle', 'Ring', 'Pinky']
    bone_names = ['Metacarpal', 'Proximal', 'Intermediate', 'Distal']
    state_names = ['STATE_INVALID', 'STATE_START', 'STATE_UPDATE', 'STATE_END']

    # 初始化函数，在控制器连接时调用
    def on_init(self, controller):
        print "Initialized"

    # 连接建立时调用
    def on_connect(self, controller):
        print "Connected"

        # 启用手势
        controller.enable_gesture(Leap.Gesture.TYPE_CIRCLE);
        controller.enable_gesture(Leap.Gesture.TYPE_KEY_TAP);
        controller.enable_gesture(Leap.Gesture.TYPE_SCREEN_TAP);
        controller.enable_gesture(Leap.Gesture.TYPE_SWIPE);

    # 连接断开时调用
    def on_disconnect(self, controller):
        # 注意：在调试器中运行时不会触发此事件。
        print "Disconnected"

    # 程序退出时调用
    def on_exit(self, controller):
        print "Exited"

    # 每一帧更新时调用
    def on_frame(self, controller):
        # 获取最新的帧并报告一些基本信息
        frame = controller.frame()

        print "Frame id: %d, timestamp: %d, hands: %d, fingers: %d, tools: %d, gestures: %d" % (
              frame.id, frame.timestamp, len(frame.hands), len(frame.fingers), len(frame.tools), len(frame.gestures()))

        # 获取手
        for hand in frame.hands:
            handType = "Left hand" if hand.is_left else "Right hand"
            print "  %s, id %d, position: %s" % (
                handType, hand.id, hand.palm_position)

            # 获取手的法向量和方向
            normal = hand.palm_normal
            direction = hand.direction

            # 计算手的俯仰、横滚和偏航角度
            print "  pitch: %f degrees, roll: %f degrees, yaw: %f degrees" % (
                direction.pitch * Leap.RAD_TO_DEG,
                normal.roll * Leap.RAD_TO_DEG,
                direction.yaw * Leap.RAD_TO_DEG)

            # 获取手臂骨骼
            arm = hand.arm
            print "  Arm direction: %s, wrist position: %s, elbow position: %s" % (
                arm.direction,
                arm.wrist_position,
                arm.elbow_position)

            # 获取手指
            for finger in hand.fingers:
                print "    %s finger, id: %d, length: %fmm, width: %fmm" % (
                    self.finger_names[finger.type],
                    finger.id,
                    finger.length,
                    finger.width)

                # 获取骨骼
                for b in range(0, 4):
                    bone = finger.bone(b)
                    print "      Bone: %s, start: %s, end: %s, direction: %s" % (
                        self.bone_names[bone.type],
                        bone.prev_joint,
                        bone.next_joint,
                        bone.direction)

        # 获取工具
        for tool in frame.tools:
            print "  Tool id: %d, position: %s, direction: %s" % (
                tool.id, tool.tip_position, tool.direction)

        # 获取手势
        for gesture in frame.gestures():
            if gesture.type == Leap.Gesture.TYPE_CIRCLE:
                circle = CircleGesture(gesture)

                # 使用指向点与圆环法向量之间的角度来确定顺时针或逆时针方向
                if circle.pointable.direction.angle_to(circle.normal) <= Leap.PI/2:
                    clockwiseness = "clockwise"
                else:
                    clockwiseness = "counterclockwise"

                # 计算自上一帧以来的扫过角度
                swept_angle = 0
                if circle.state != Leap.Gesture.STATE_START:
                    previous_update = CircleGesture(controller.frame(1).gesture(circle.id))
                    swept_angle =  (circle.progress - previous_update.progress) * 2 * Leap.PI

                print "  Circle id: %d, %s, progress: %f, radius: %f, angle: %f degrees, %s" % (
                        gesture.id, self.state_names[gesture.state],
                        circle.progress, circle.radius, swept_angle * Leap.RAD_TO_DEG, clockwiseness)

            if gesture.type == Leap.Gesture.TYPE_SWIPE:
                swipe = SwipeGesture(gesture)
                print "  Swipe id: %d, state: %s, position: %s, direction: %s, speed: %f" % (
                        gesture.id, self.state_names[gesture.state],
                        swipe.position, swipe.direction, swipe.speed)

            if gesture.type == Leap.Gesture.TYPE_KEY_TAP:
                keytap = KeyTapGesture(gesture)
                print "  Key Tap id: %d, %s, position: %s, direction: %s" % (
                        gesture.id, self.state_names[gesture.state],
                        keytap.position, keytap.direction )

            if gesture.type == Leap.Gesture.TYPE_SCREEN_TAP:
                screentap = ScreenTapGesture(gesture)
                print "  Screen Tap id: %d, %s, position: %s, direction: %s" % (
                        gesture.id, self.state_names[gesture.state],
                        screentap.position, screentap.direction )

        # 如果手或手势不为空，则打印空行
        if not (frame.hands.is_empty and frame.gestures().is_empty):
            print ""

    # 定义状态字符串函数
    def state_string(self, state):
        if state == Leap.Gesture.STATE_START:
            return "STATE_START"

        if state == Leap.Gesture.STATE_UPDATE:
            return "STATE_UPDATE"

        if state == Leap.Gesture.STATE_STOP:
            return "STATE_STOP"

        if state == Leap.Gesture.STATE_INVALID:
            return "STATE_INVALID"

def main():
     # 创建 SampleListener 对象和 Leap 控制器对象
    listener = SampleListener()
    controller = Leap.Controller()

    # 将样本监听器添加到控制器中，接收控制器发出的事件
    controller.add_listener(listener)

    # 保持进程运行，直到按下 Enter 键
    print "Press Enter to quit..."
    try:
        sys.stdin.readline()
    except KeyboardInterrupt:
        pass
    finally:
        # 在完成时移除样本监听器
        controller.remove_listener(listener)

# 如果此脚本作为独立脚本运行，则执行主函数
if __name__ == "__main__":
    main()
